package sensitivity;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JPanel;

public class SensitivityPanel extends JPanel {

	/** The radius of the X-circle. */
	private static final int CIRCLE_RADIUS = 50;

	private static final SimpleDateFormat FILE_NAME_FORMAT = new SimpleDateFormat("MM_dd_yyyy_hh_mm_ss");

	private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("EEE MMM dd yy hh:mm:ss.SSS");

	private static final long BLANK_DELAY = 500;

	private long _lastDisplayTime;

	/** Used to generate random numbers. */
	private Random _random = new Random(Calendar.getInstance().getTimeInMillis());

	private BufferedWriter _outputFileWriter = null;

	private int _clickCount = 0;

	private int participantNumber = 0;

	private int numberOfTouches = 1;
	
	private Timer _timer = new Timer();
	
	private JButton _xButton;

	public SensitivityPanel(int width, int height, int participantNumber) {
		this.participantNumber = participantNumber;
		setLayout(null);
		setSize(width, height);
		setMinimumSize(getSize());
		setPreferredSize(getSize());

		String outputDirectory = System.getProperty("outputDirectory");
		if (outputDirectory == null) {
			outputDirectory = System.getProperty("user.home");
		}
		String outputFilePath = outputDirectory + "/Sensitivity_"
				+ FILE_NAME_FORMAT.format(new Date()) + ".txt";
		try {
			_outputFileWriter = new BufferedWriter(new FileWriter(
					outputFilePath));
			_outputFileWriter.write("Participant Number,Touch,x,y,Reaction Time (ms)");
			_outputFileWriter.newLine();
			_outputFileWriter.flush();

		} catch (IOException e) {
			e.printStackTrace();
		}
		
		BufferedImage bufferedImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
		Graphics2D graphics2d = bufferedImage.createGraphics();
		
		// Draw background.
		Rectangle2D.Double backgroundSquare = new Rectangle2D.Double(0, 0, 2 * CIRCLE_RADIUS, 2 * CIRCLE_RADIUS);
		graphics2d.setColor(getBackground());
		graphics2d.fill(backgroundSquare);
		
		// Draw circle.
		graphics2d.setColor(Color.BLACK);
		Ellipse2D.Double circle = new Ellipse2D.Double(
				0, 0,
				(2 * CIRCLE_RADIUS), (2 * CIRCLE_RADIUS));
		graphics2d.fill(circle);

		// Draw X.
		graphics2d.setColor(Color.RED);
		double difference = CIRCLE_RADIUS / Math.sqrt(2.0);
		Line2D.Double line1 = new Line2D.Double(CIRCLE_RADIUS
				- difference, CIRCLE_RADIUS - difference,
				CIRCLE_RADIUS + difference, CIRCLE_RADIUS
				+ difference);
		graphics2d.draw(line1);
		Line2D.Double line2 = new Line2D.Double(CIRCLE_RADIUS
				- difference, CIRCLE_RADIUS + difference,
				CIRCLE_RADIUS + difference, CIRCLE_RADIUS
				- difference);
		graphics2d.draw(line2);
		ImageIcon image = new ImageIcon(bufferedImage);
		_xButton = new JButton(image);
		int dimension = 2 * CIRCLE_RADIUS;
		_xButton.setSize(dimension, dimension);
//		_xButton.setBackground(getBackground());
		_xButton.setBorder(null);
		
		_xButton.addActionListener(new SensitivityActionListener());
		updateXPosition();
	}

	/**
	 * Generates a random position for the circle, 
	 * within the bounds of this panel.
	 */
	private void updateXPosition() {
		removeAll();
		setVisible(false);
		setVisible(true);
		_timer.schedule(new TimerTask() {

			@Override
			public void run() {
				int buttonWidth = _xButton.getWidth();
				int buttonX = _xButton.getX();
				int buttonY = _xButton.getY();
				int newX = _random.nextInt(getWidth() - buttonWidth);
				int newY = _random.nextInt(getHeight() - buttonWidth);
				while (Point.distance(newX, newY, buttonX, buttonY) < buttonWidth) {
					newX = _random.nextInt(getWidth() - buttonWidth);
					newY = _random.nextInt(getHeight() - buttonWidth);
				}
				_xButton.setLocation(newX, newY);
				add(_xButton);
				setVisible(false);
				setVisible(true);
				Date displayDate = new Date();
				_lastDisplayTime = displayDate.getTime();
			}
			
		}, BLANK_DELAY);
	}

	public void closeFile() {
		try {
			_outputFileWriter.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Listens for the user clicking on the 
	 * X with a mouse, to log the time the user clicked 
	 * and to cause the X to be moved
	 * to another random location.
	 * 
	 * @author Sean Megeath
	 */
	private class SensitivityActionListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			writeClick();
			updateXPosition();
			_clickCount++;
			if (_clickCount == 200) {
				System.exit(0);
			}
		}

	}

	private void writeClick() {
		Date clickDate = new Date();
		long clickTime = clickDate.getTime();
		int buttonCenterX = _xButton.getX() + (_xButton.getWidth()/2);
		int buttonCenterY = _xButton.getY() + (_xButton.getHeight() / 2);
		String update = participantNumber + "," + numberOfTouches + "," + buttonCenterX + "," + buttonCenterY + "," + (clickTime - _lastDisplayTime);
		try {
			_outputFileWriter.write(update);
			_outputFileWriter.newLine();
			_outputFileWriter.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}
		numberOfTouches++;
		if (numberOfTouches > 200) {
			System.exit(0);
		}
	}

}
